﻿using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using Wicture.DbRESTFul;
using Wicture.DbRESTFul.Cache;
using Wicture.DbRESTFul.SQL;
using Wicture.EPC.Common;
using Wicture.EPC.Common.Biz;
using Wicture.EPC.Service.V1.Models;
using Wicture.EPC.Service.V1.Models.Jaguar;
using Wicture.EPC.Service.V1.Repository;
using Wicture.EPC.Service.V1.Services.EPC.OnlineQuery;

namespace Wicture.EPC.Service.V1.QueryInterceptors.Interceptors
{
    public class JaguarQueryInterceptor : BaseQueryInterceptor
    {
        private readonly string[] brandCodes = new string[] { "jaguar", "landrover" };

        public override string[] BrandCodes => brandCodes;
        protected override List<Query_MainGroupResult> GetMainGroup(DbRESTFulRepository repository, JObject param)
        {
            var result = repository.Invoke<Query_MainGroupResult>(CSIs.Query_Main_Group_For_SelectorId, param);
            return FilterMaingroupsByModelFeatures(repository, result, param.Value<string>(ParamFields._selectorId));
        }
        protected override IEnumerable<Query_SubGroupResult> GetSubGroup(DbRESTFulRepository repository, JObject param)
        {
            IEnumerable<Query_SubGroupResult> results = repository.Invoke<Query_SubGroupResult>(CSIs.Query_SubGroup_For_Jaguar, param);
            return FilterSubgroupsByModelFeatures(repository, results, param.Value<string>(ParamFields._selectorId)).ToList();
        }

        protected override List<Query_PartsResult> GetParts(DbRESTFulRepository repository, JObject param)
        {
            var results = repository.Invoke<Query_PartsResult>(CSIs.Query_Parts_For_Jaguar, param);
            return FilterPartsByModelFeatures(repository, results, param.Value<string>(ParamFields._selectorId));
        }
        protected override List<Query_PartsResult> BuildPartResults(List<Query_PartsResult> result)
        {
            List<Query_PartsResult> res = new List<Query_PartsResult>();

            //特殊处理,超过1w取3千
            if (result != null && result.Count() > 3000)
            {
                var groupedList = result.GroupBy(e => e.imageSN);
                foreach (var item in groupedList)
                {
                    res.AddRange(item.Where(e => e.belongToVin).Take(20));
                }
            }
            else
            {
                res = result;
            }

            if (res != null && res.Any())
            {
                res = res.OrderBy(e => e.imageSN).ToList();
                foreach (var item in res)
                {
                    if (!(string.IsNullOrEmpty(item.rangeStart) && string.IsNullOrEmpty(item.rangeEnd)))
                    {
                        string range = $"（{item.rangeStart ?? ""} - {item.rangeEnd ?? ""}）";
                        item.modelNotes = range + item.modelNotes ?? "";
                    }
                }
            }
            //List<Query_PartsResult> ret = new List<Query_PartsResult>();
            //var groupedParts = result.GroupBy(e => e.id);
            //foreach (var item in groupedParts)
            //{
            //    ret.AddRange(item.Take(1));
            //}

            //foreach (var info in ret)
            //{
            //    info.featureCodes = "";
            //    info.modelFilter = "";
            //}
            //return ret;
            return res;
        }

        protected override void FilterPartsByVin(DbRESTFulRepository repository, ref List<Query_PartsResult> result, string vin, string selectorId)
        {
            if (result == null || !result.Any())
            {
                return;
            }
            if (!string.IsNullOrEmpty(vin))
            {
                var vinInfo = repository.Invoke(CSIs.Query_Vin_By_Code_For_Jaguar, new { vin });
                if (vinInfo != null)
                {
                    List<Feature_Jaguar> featuresList, vinFeatureList;
                    HandleFeatureIds(repository, result, vinInfo.featureIdListStr, out featuresList, out vinFeatureList);
                    foreach (var info in result)
                    {
                        if (!string.IsNullOrEmpty(info.rangeStart) && CompareVinRange(vin, info.rangeStart) < 0)
                        {
                            info.belongToVin = false;
                            continue;
                        }

                        if (!string.IsNullOrEmpty(info.rangeEnd) && CompareVinRange(vin, info.rangeEnd) > 0)
                        {
                            info.belongToVin = false;
                            continue;
                        }
                        bool tmpRes = false;
                        if (string.IsNullOrEmpty(info.featureCodes))
                        {
                            tmpRes = true;
                        }
                        else
                        {
                            List<string> orFeatureIdList = info.featureCodes.Split(new char[] { '|' }).ToList();
                            foreach (var item in orFeatureIdList)
                            {
                                List<string> andFeatureIdList = item.Split(new char[] { ',' }).ToList();
                                List<Feature_Jaguar> andFeatures = featuresList.Where(e => andFeatureIdList.Contains(e.featureId.ToString())).ToList();

                                bool andBoolRes = true;
                                foreach (var andItem in andFeatures)
                                {
                                    var tmpFeature = vinFeatureList.FirstOrDefault(e => e.familyId == andItem.familyId);
                                    if (tmpFeature != null && tmpFeature.featureId != andItem.featureId && !(tmpFeature.similarFeatureIds ?? "").Contains(andItem.featureId.ToString()))
                                    {
                                        if (!CheckSameFamilyFeature(tmpFeature, andItem))
                                        {
                                            andBoolRes = false;
                                            break;
                                        }
                                    }
                                }
                                if (andBoolRes)
                                {
                                    tmpRes = true;
                                    break;
                                }
                            }
                        }
                        if (!tmpRes)
                        {
                            info.belongToVin = false;
                        }
                    }
                }
            }
        }

        protected void FilterPartsByVin2(DbRESTFulRepository repository, ref List<PartCatalogResult> result, string vin, string selectorId, string vinFeatureIdListStr)
        {
            if (result == null || !result.Any())
            {
                return;
            }
            if (string.IsNullOrEmpty(vin))
            {
                return;
            }
            List<Feature_Jaguar> featuresList, vinFeatureList;
            HandleFeatureIds2(repository, result, vinFeatureIdListStr, out featuresList, out vinFeatureList);
            foreach (var info in result)
            {
                if (!string.IsNullOrEmpty(info.rangeStart) && CompareVinRange(vin, info.rangeStart) < 0)
                {
                    info.belongToVin = false;
                    continue;
                }

                if (!string.IsNullOrEmpty(info.rangeEnd) && CompareVinRange(vin, info.rangeEnd) > 0)
                {
                    info.belongToVin = false;
                    continue;
                }
                bool tmpRes = false;
                if (string.IsNullOrEmpty(info.featureCodes))
                {
                    tmpRes = true;
                }
                else
                {
                    List<string> orFeatureIdList = info.featureCodes.Split(new char[] { '|' }).ToList();
                    foreach (var item in orFeatureIdList)
                    {
                        List<string> andFeatureIdList = item.Split(new char[] { ',' }).ToList();
                        List<Feature_Jaguar> andFeatures = featuresList.Where(e => andFeatureIdList.Contains(e.featureId.ToString())).ToList();

                        bool andBoolRes = true;
                        foreach (var andItem in andFeatures)
                        {
                            var tmpFeature = vinFeatureList.FirstOrDefault(e => e.familyId == andItem.familyId);
                            if (tmpFeature != null && tmpFeature.featureId != andItem.featureId && !(tmpFeature.similarFeatureIds ?? "").Contains(andItem.featureId.ToString()))
                            {
                                if (!CheckSameFamilyFeature(tmpFeature, andItem))
                                {
                                    andBoolRes = false;
                                    break;
                                }
                            }
                        }
                        if (andBoolRes)
                        {
                            tmpRes = true;
                            break;
                        }
                    }
                }
                if (!tmpRes)
                {
                    info.belongToVin = false;
                }
            }
        }

        void HandleFeatureIds(DbRESTFulRepository repository, List<Query_PartsResult> partusages, string vinFeatureIds, out List<Feature_Jaguar> allFeatures, out List<Feature_Jaguar> vinFeatures)
        {
            List<string> allFeatureIds = new List<string>();
            List<string> featureIds_vin = new List<string>();
            if (!string.IsNullOrEmpty(vinFeatureIds))
            {
                featureIds_vin = vinFeatureIds.Split(new char[] { ',' }).ToList();
                allFeatureIds.AddRange(featureIds_vin);
            }

            foreach (var info in partusages)
            {
                if (!string.IsNullOrEmpty(info.featureCodes))
                {
                    List<string> orFeatureIdList = info.featureCodes.Split(new char[] { '|' }).ToList();
                    foreach (var item in orFeatureIdList)
                    {
                        List<string> andFeatureIdList = item.Split(new char[] { ',' }).ToList();
                        foreach (var f in andFeatureIdList)
                        {
                            if (!allFeatureIds.Contains(f))
                            {
                                allFeatureIds.Add(f);
                            }
                        }
                    }
                }
            }
            allFeatures = GetFeaturesByIds(repository, allFeatureIds);
            vinFeatures = allFeatures.Where(e => featureIds_vin.Contains(e.featureId.ToString())).ToList();
        }
        void HandleFeatureIds2(DbRESTFulRepository repository, List<PartCatalogResult> partusages, string vinFeatureIds, out List<Feature_Jaguar> allFeatures, out List<Feature_Jaguar> vinFeatures)
        {
            List<string> allFeatureIds = new List<string>();
            List<string> featureIds_vin = new List<string>();
            if (!string.IsNullOrEmpty(vinFeatureIds))
            {
                featureIds_vin = vinFeatureIds.Split(new char[] { ',' }).ToList();
                allFeatureIds.AddRange(featureIds_vin);
            }

            foreach (var info in partusages)
            {
                if (!string.IsNullOrEmpty(info.featureCodes))
                {
                    List<string> orFeatureIdList = info.featureCodes.Split(new char[] { '|' }).ToList();
                    foreach (var item in orFeatureIdList)
                    {
                        List<string> andFeatureIdList = item.Split(new char[] { ',' }).ToList();
                        foreach (var f in andFeatureIdList)
                        {
                            if (!allFeatureIds.Contains(f))
                            {
                                allFeatureIds.Add(f);
                            }
                        }
                    }
                }
            }
            allFeatures = GetFeaturesByIds(repository, allFeatureIds);
            vinFeatures = allFeatures.Where(e => featureIds_vin.Contains(e.featureId.ToString())).ToList();
        }
        private int CompareVinRange(string vin, string vinRange)
        {
            vin = vin.Substring(vin.Length - vinRange.Length, vinRange.Length);
            for (int i = 0; i < vinRange.Length; i++)
            {
                var a = vin[i];
                var b = vinRange[i];
                if (a > b)
                {
                    return 1;
                }
                else if (a < b)
                {
                    return -1;
                }
            }
            return 0;
        }

        protected override List<Query_SubGroupResult> BuildSubGroupResults(List<Query_SubGroupResult> result)
        {
            if (result != null && result.Any())
            {
                result.ForEach(e =>
                {
                    if (!string.IsNullOrEmpty(e.applicableModel))
                    {
                        var applicaleList = e.applicableModel.Split(";");
                        e.applicableModel = string.Join("$$", applicaleList.Distinct());
                    }
                    if (!(string.IsNullOrEmpty(e.rangeStart) && string.IsNullOrEmpty(e.rangeEnd)))
                    {
                        string range = $"（{e.rangeStart ?? ""} - {e.rangeEnd ?? ""}）";
                        e.applicableModel = $"{range}$${e.applicableModel}";
                    }

                });
            }
            return result;
        }

        protected override IEnumerable<dynamic> GetHotPoints(DbRESTFulRepository repository, JObject param)
        {
            return repository.Invoke(CSIs.Query_HotPoints_For_Jaguar, param);
        }

        public override object QueryModel(DbRESTFulRepository repository, JObject param)
        {
            Get_Model_InfoParam modelParam = param.ToObject<Get_Model_InfoParam>();
            if (!string.IsNullOrEmpty(modelParam.vin))
            {
                var vinInfo = repository.Invoke(CSIs.Query_Vin_By_Code_For_Jaguar, modelParam);
                if (vinInfo == null)
                {
                    throw new LogicalException($"未找到该Vin码(jaguar){modelParam.vin}", 610);
                }
                return BuildVinResult(vinInfo, repository);
            }
            else
            {
                Get_Model_InfoResult result = new Get_Model_InfoResult();
                var ids = modelParam.id.Split("_");
                if (ids.Count() > 1)
                {
                    modelParam.id = ids[1];
                }
                var model = repository.Invoke(CSIs.Get_Model, modelParam);
                if (model != null)
                {
                    result = JObject.FromObject(model).ToObject<Get_Model_InfoResult>();
                    result.props = GetModelProps(repository, param);
                }
                return result;
            }
        }

        public override object OnlineQueryVin(DbRESTFulRepository repository, JObject param)
        {
            Get_Model_InfoParam modelParam = param.ToObject<Get_Model_InfoParam>();

            HandleEpcOnlineVin(modelParam, repository);

            var vinInfo = repository.Invoke(CSIs.Query_Vin_By_Code_For_Jaguar, modelParam);
            if (vinInfo == null)
            {
                throw new LogicalException($"未找到该Vin码(jaguar){modelParam.vin}", 610);
            }
            return BuildVinResult(vinInfo, repository);
        }

        public void HandleEpcOnlineVin(Get_Model_InfoParam param, DbRESTFulRepository repository)
        {
            string vin = param.vin;
            string brandCode = param.brandCode;

            EPCOnlineQueryService epcOnlineQueryService = new EPCOnlineQueryService();
            var queryRes = epcOnlineQueryService.QueryVin(vin, brandCode);

            JlrVinInfo vinInfo = null;
            JlrVinFeatureInfo featureInfo = null;
            CheckOnlineVinQueryRes(queryRes, vin, out vinInfo, out featureInfo);

            if (vinInfo != null)
            {
                vinInfo.createtime = DateTime.Now;

                //转化时间
                //09/21/2004 08:00:00
                DateTime dt1 = Convert.ToDateTime(vinInfo.productionDate);
                var dateTimeStamp = DateOperator.GetTimeStamp(dt1);
                vinInfo.productionDate = dateTimeStamp;
                if (vinInfo.featureIdList != null && vinInfo.featureIdList.Any())
                {
                    vinInfo.featureIdListStr = string.Join(",", vinInfo.featureIdList);
                }
                if (vinInfo.primaryFeatureDescriptionList != null && vinInfo.primaryFeatureDescriptionList.Any())
                {
                    vinInfo.primaryFeatureDescriptionListStr = string.Join(",", vinInfo.primaryFeatureDescriptionList);
                }

                repository.Invoke(CSIs.Insert_Vin_For_Jaguar, vinInfo);

                if (featureInfo != null)
                {
                    List<JlrFamilyModel> familyList = new List<JlrFamilyModel>();
                    List<JlrFeatureModel> featureList = new List<JlrFeatureModel>();
                    //副配置
                    if (featureInfo.minorFeatureCodes != null && featureInfo.minorFeatureCodes.Any())
                    {
                        foreach (var item in featureInfo.minorFeatureCodes)
                        {
                            if (familyList.FirstOrDefault(e => e.id == item.familyId) == null)
                            {
                                familyList.Add(new JlrFamilyModel() { id = item.familyId, name = item.name, familyType = Enum.FamilyType.Minor.ToString() });
                            }
                            if (item.features != null && item.features.Any())
                            {
                                foreach (var f in item.features)
                                {
                                    if (featureList.FirstOrDefault(e => e.id == f.id) == null)
                                    {
                                        featureList.Add(new JlrFeatureModel { id = f.id, name = f.name, familyId = item.familyId });
                                    }
                                }
                            }
                        }
                    }
                    //主配置
                    if (featureInfo.primaryFeatureCodes != null && featureInfo.primaryFeatureCodes.Any())
                    {
                        foreach (var item in featureInfo.primaryFeatureCodes)
                        {
                            if (familyList.FirstOrDefault(e => e.id == item.familyId) == null)
                            {
                                familyList.Add(new JlrFamilyModel() { id = item.familyId, name = item.name, familyType = Enum.FamilyType.Primary.ToString(), sortIndex = item.sortIndex });
                            }
                            if (item.features != null && item.features.Any())
                            {
                                foreach (var f in item.features)
                                {
                                    if (featureList.FirstOrDefault(e => e.id == f.id) == null)
                                    {
                                        featureList.Add(new JlrFeatureModel { id = f.id, name = f.name, familyId = item.familyId, sortIndex = f.sortIndex });
                                    }
                                }
                            }
                        }
                    }
                    if (familyList.Any())
                    {
                        repository.Invoke(CSIs.Insert_Families_For_Jaguar, familyList);
                    }
                    if (featureList.Any())
                    {
                        repository.Invoke(CSIs.Insert_Features_For_Jaguar, featureList);
                    }
                }
            }
        }
        //{hasError: false, errorMessage: '', data: {vin: task.params.vin, result01: rst, result02: rst01}}
        void CheckOnlineVinQueryRes(JObject queryRes, string vin, out JlrVinInfo vinInfoOut, out JlrVinFeatureInfo featureInfoOut)
        {
            if (queryRes == null)
            {
                LoggerManager.Logger.LogError("JaguarQueryInterceptor.GetEpcOnlineVin, queryRes is null");

                throw new Exception($"系统繁忙，请稍后再试！({vin})");
            }
            bool hasError = queryRes["HasError"].ToObject<bool>();
            if (hasError)
            {
                string errMsg = queryRes["ErrorMessage"].ToObject<string>();
                LoggerManager.Logger.LogError($"JaguarQueryInterceptor.GetEpcOnlineVin, hasError,{errMsg} ");

                throw new Exception($"系统繁忙，请稍后再试！({vin})");
            }
            var data = queryRes["Data"];
            if (data == null)
            {
                LoggerManager.Logger.LogError("JaguarQueryInterceptor.GetEpcOnlineVin, data is null");

                throw new Exception($"系统繁忙，请稍后再试！({vin})");
            }
            var vinInfo = data["result01"];
            if (vinInfo == null)
            {
                LoggerManager.Logger.LogError("JaguarQueryInterceptor.GetEpcOnlineVin, vinInfo is null");

                throw new Exception($"系统繁忙，请稍后再试！({vin})");
            }
            var vinInfoResults = vinInfo["results"];
            if (vinInfoResults == null)
            {
                LoggerManager.Logger.LogError("JaguarQueryInterceptor.GetEpcOnlineVin, vinInfoResults is null");

                throw new LogicalException($"未找到该Vin码(jaguar){vin}", 610);
            }
            var vinArr = JArray.FromObject(vinInfoResults);
            if (vinArr == null || vinArr.Count <= 0)
            {
                LoggerManager.Logger.LogError("JaguarQueryInterceptor.GetEpcOnlineVin, vinArr is null");

                throw new LogicalException($"未找到该Vin码(jaguar){vin}", 610);
            }

            vinInfoOut = vinArr[0].ToObject<JlrVinInfo>();
            if (string.IsNullOrEmpty(vinInfoOut.productionDate))
            {
                LoggerManager.Logger.LogError("JaguarQueryInterceptor.GetEpcOnlineVin, productionDate is null");

                throw new LogicalException($"未找到该Vin码(jaguar){vin}", 610);
            }

            var featureInfoResult = data["result02"];
            if (featureInfoResult == null)
            {
                LoggerManager.Logger.LogError("JaguarQueryInterceptor.GetEpcOnlineVin, featureInfoResult is null");
            }

            featureInfoOut = featureInfoResult.ToObject<JlrVinFeatureInfo>();
        }

        private Get_Model_InfoResult BuildVinResult(dynamic vinInfo, DbRESTFulRepository repository)
        {
            Get_Model_InfoResult result = new Get_Model_InfoResult();
            string modelCode = vinInfo.code;
            string featureIdListStr = vinInfo.featureIdListStr;
            string[] featureIds = featureIdListStr.Split(',');
            result = JObject.FromObject(vinInfo).ToObject<Get_Model_InfoResult>();
            result.props = new List<Get_Model_InfoResult._props>();
            result.props.Add(new Get_Model_InfoResult._props { key = "生产日期", value = DateOperator.GetTime(vinInfo.productionDate).ToString("yyyy-MM-dd") });
            List<Feature_Jaguar> features = repository.Invoke<Feature_Jaguar>(CSIs.Get_Features_For_Jaguar, new { modelCode, featureIds });
            result.props.AddRange(features.Where(q => q.familyType == "Primary").OrderBy(q => q.familyId).Select(q => new Get_Model_InfoResult._props { key = q.familyName, value = q.featureName }));
            result.features = new List<Get_Model_InfoResult._features>();
            result.features.AddRange(features.Where(q => q.familyType == "Minor").Select(q => new Get_Model_InfoResult._features { key = q.familyName, value = q.featureName }));
            return result;
        }

        protected override List<Query_MainGroupResult> FilterMainGroupsByVin(DbRESTFulRepository repository, List<Query_MainGroupResult> maingroups, string vin)
        {
            if (maingroups == null || !maingroups.Any())
            {
                return null;
            }
            List<Query_MainGroupResult> result = maingroups;
            if (string.IsNullOrEmpty(vin))
            {
                return result;
            }
            var vinInfo = repository.Invoke(CSIs.Query_Vin_By_Code_For_Jaguar, new { vin });
            if (vinInfo != null)
            {
                result = FilterMaingroupsByVinFeatures(repository, maingroups, vinInfo.featureIdListStr);
            }
            return result;
        }

        protected override List<Query_SubGroupResult> FilterSubGroupsByVin(DbRESTFulRepository repository, List<Query_SubGroupResult> results, JObject param)
        {
            if (results == null || !results.Any())
            {
                return null;
            }
            var vin = param.Value<string>(ParamFields._vin);
            if (!string.IsNullOrEmpty(vin))
            {
                var vinInfo = repository.Invoke(CSIs.Query_Vin_By_Code_For_Jaguar, new { vin });
                if (vinInfo != null)
                {
                    List<string> allFeatureIds = new List<string>();
                    List<string> featureIds_vin = ((string)vinInfo.featureIdListStr).Split(new char[] { ',' }).ToList();
                    allFeatureIds.AddRange(featureIds_vin);

                    var subgroupids = results.Select(e => e.id);
                    List<JlrSubGroupFilter> _subgroupFilters = repository.Invoke<JlrSubGroupFilter>(CSIs.Query_Subgroup_Filter_For_Jaguar, new { subgroupids });
                    if (_subgroupFilters == null || !_subgroupFilters.Any())
                    {
                        return results;
                    }
                    var subgroupFilterIds = _subgroupFilters.Select(e => e.filterIds);
                    foreach (var item in subgroupFilterIds)
                    {
                        allFeatureIds.AddRange(item.Split(new char[] { ',' }));
                    }
                    allFeatureIds = allFeatureIds.Distinct().ToList();

                    List<Feature_Jaguar> featuresList = GetFeaturesByIds(repository, allFeatureIds);
                    List<Feature_Jaguar> vinFeatureList = featuresList.Where(e => featureIds_vin.Contains(e.featureId.ToString())).ToList();
                    foreach (var info in results)
                    {
                        bool tmpRes = false;
                        var subFilters = _subgroupFilters.Where(e => e.subgroupId.ToString() == info.id);
                        if (subFilters == null || !subFilters.Any())
                        {
                            tmpRes = true;
                        }
                        else
                        {
                            foreach (var item in subFilters)
                            {
                                if (!string.IsNullOrEmpty(item.rangeStart) && CompareVinRange(vin, item.rangeStart) < 0)
                                {
                                    continue;
                                }

                                if (!string.IsNullOrEmpty(item.rangeEnd) && CompareVinRange(vin, item.rangeEnd) > 0)
                                {
                                    continue;
                                }

                                if (string.IsNullOrEmpty(item.filterIds))
                                {
                                    tmpRes = true;
                                    break;
                                }
                                else
                                {
                                    List<string> andFeatureIdList = item.filterIds.Split(new char[] { ',' }).ToList();
                                    List<Feature_Jaguar> andFeatures = featuresList.Where(e => andFeatureIdList.Contains(e.featureId.ToString())).ToList();

                                    bool andBoolRes = true;
                                    foreach (var andItem in andFeatures)
                                    {
                                        var tmpFeature = vinFeatureList.FirstOrDefault(e => e.familyId == andItem.familyId);
                                        if (!CheckSameFamilyFeature(tmpFeature, andItem))
                                        {
                                            andBoolRes = false;
                                            break;
                                        }
                                    }
                                    if (andBoolRes)
                                    {
                                        tmpRes = true;
                                        break;
                                    }
                                }
                            }
                        }
                        if (!tmpRes)
                        {
                            info.belongTo = false;
                        }
                    }

                }
            }
            return results;
        }
        private List<Query_SubGroupResult> FilterSubGroupsByVin2(DbRESTFulRepository repository, List<Query_SubGroupResult> results, string vin, string vinFeatureIdListStr)
        {
            if (results == null || !results.Any())
            {
                return null;
            }
            if (string.IsNullOrEmpty(vin))
            {
                return results;
            }
            List<string> allFeatureIds = new List<string>();

            List<string> featureIds_vin = vinFeatureIdListStr?.Split(new char[] { ',' }).ToList();
            allFeatureIds.AddRange(featureIds_vin);

            var subgroupids = results.Select(e => e.id);
            List<JlrSubGroupFilter> _subgroupFilters = repository.Invoke<JlrSubGroupFilter>(CSIs.Query_Subgroup_Filter_For_Jaguar, new { subgroupids });
            if (_subgroupFilters == null || !_subgroupFilters.Any())
            {
                return results;
            }
            var subgroupFilterIds = _subgroupFilters.Select(e => e.filterIds);
            foreach (var item in subgroupFilterIds)
            {
                allFeatureIds.AddRange(item.Split(new char[] { ',' }));
            }
            allFeatureIds = allFeatureIds.Distinct().ToList();

            List<Feature_Jaguar> featuresList = GetFeaturesByIds(repository, allFeatureIds);
            List<Feature_Jaguar> vinFeatureList = featuresList.Where(e => featureIds_vin.Contains(e.featureId.ToString())).ToList();
            foreach (var info in results)
            {
                bool tmpRes = false;
                var subFilters = _subgroupFilters.Where(e => e.subgroupId.ToString() == info.id);
                if (subFilters == null || !subFilters.Any())
                {
                    tmpRes = true;
                }
                else
                {
                    foreach (var item in subFilters)
                    {
                        if (!string.IsNullOrEmpty(item.rangeStart) && CompareVinRange(vin, item.rangeStart) < 0)
                        {
                            continue;
                        }

                        if (!string.IsNullOrEmpty(item.rangeEnd) && CompareVinRange(vin, item.rangeEnd) > 0)
                        {
                            continue;
                        }

                        if (string.IsNullOrEmpty(item.filterIds))
                        {
                            tmpRes = true;
                            break;
                        }
                        else
                        {
                            List<string> andFeatureIdList = item.filterIds.Split(new char[] { ',' }).ToList();
                            List<Feature_Jaguar> andFeatures = featuresList.Where(e => andFeatureIdList.Contains(e.featureId.ToString())).ToList();

                            bool andBoolRes = true;
                            foreach (var andItem in andFeatures)
                            {
                                var tmpFeature = vinFeatureList.FirstOrDefault(e => e.familyId == andItem.familyId);
                                if (!CheckSameFamilyFeature(tmpFeature, andItem))
                                {
                                    andBoolRes = false;
                                    break;
                                }
                            }
                            if (andBoolRes)
                            {
                                tmpRes = true;
                                break;
                            }
                        }
                    }
                }
                if (!tmpRes)
                {
                    info.belongTo = false;
                }
            }
            return results;
        }


        string _areaReg = @"^\([\+|-]\)\s*" + "\"" + "\\S+" + "\"";
        bool AreaCheck(string input)
        {
            bool result = false;

            Regex reg = new Regex(_areaReg, RegexOptions.IgnoreCase);
            result = reg.IsMatch(input);
            return result;
        }
        private bool CheckSameFamilyFeature(Feature_Jaguar vinFeature, Feature_Jaguar partFeature)
        {
            bool ret = true;
            if (vinFeature != null && vinFeature.featureId != partFeature.featureId && !(vinFeature.similarFeatureIds ?? "").Contains(partFeature.featureId.ToString()))
            {
                if (!CheckFilterContent(vinFeature.featureName, partFeature.featureName))
                {
                    int familyId = vinFeature.familyId;
                    //地区
                    if (familyId == 232)
                    {
                        if (AreaCheck(vinFeature.featureName) && AreaCheck(partFeature.featureName))
                        {
                            string vinKey = vinFeature.featureName.Substring(1, 1);
                            List<string> vinValues = new List<string>();

                            Regex reg = new Regex(_areaReg, RegexOptions.IgnoreCase);
                            MatchCollection collections = reg.Matches(vinFeature.featureName);
                            if (collections != null && collections.Any())
                            {
                                vinValues = collections[0].Value.Replace($"({vinKey})", "").Trim(new char[] { '"' }).Split(new char[] { '/' }).ToList();
                            }

                            string partKey = partFeature.featureName.Substring(1, 1);
                            List<string> partValues = new List<string>();
                            collections = reg.Matches(partFeature.featureName);
                            if (collections != null && collections.Any())
                            {
                                partValues = collections[0].Value.Replace($"({partKey})", "").Trim(new char[] { '"' }).Split(new char[] { '/' }).ToList();
                            }

                            if (vinKey == "+")
                            {
                                //交集
                                if (partKey == "+")
                                {
                                    var intersections = vinValues.Intersect(partValues);
                                    if (intersections != null && intersections.Any())
                                    {
                                        return true;
                                    }
                                }
                                //差集
                                else if (partKey == "-")
                                {
                                    var excepts = vinValues.Except(partValues);
                                    if (excepts != null && excepts.Any())
                                    {
                                        return true;
                                    }
                                }
                            }
                            else if (vinKey == "-")
                            {
                                if (partKey == "+")
                                {
                                    //差集
                                    var excepts = partValues.Except(vinValues);
                                    if (excepts != null && excepts.Any())
                                    {
                                        return true;
                                    }
                                }
                                else if (partKey == "-")
                                {
                                    return true;
                                }
                            }
                        }
                    }
                    return false;
                }
            }
            return ret;
        }
        private bool CheckFilterContent(string content1, string content2)
        {
            bool result = false;
            if (!string.IsNullOrEmpty(content1) && !string.IsNullOrEmpty(content2))
            {
                if (content1.Trim().Equals(content2.Trim()))
                {
                    result = true;
                }
            }
            return result;
        }

        public override object QueryPartDetail(DbRESTFulRepository repository, JObject param)
        {
            param.RemoveEmptyValues();
            var brandCode = param.Value<string>(ParamFields._brandCode);
            var partId = param.Value<string>(ParamFields._partId);
            var partCode = param.Value<string>(ParamFields._partCode);
            dynamic data = null;

            if (string.IsNullOrEmpty(partId))
            {
                data = repository.Invoke(CSIs.Get_Part_Detail_For_Jaguar, new { partCode, brandCode });
            }
            else
            {
                data = repository.Invoke(CSIs.Get_Usage_Detail_For_Jaguar, param);
            }
            if (data == null) return null;
            // 1、基本信息赋值
            Query_Part_DetailResult result = JObject.FromObject(data).ToObject<Query_Part_DetailResult>();

            result.replacements = new List<Query_Part_DetailResult._replacement>();
            //3.替换件处理
            if (!string.IsNullOrEmpty(data.supersession))
            {
                List<Query_Part_DetailResult._replacement> replacements = repository.Invoke<Query_Part_DetailResult._replacement>(CSIs.Query_Parts_By_Codes, new { partCodes = data.supersession.Split(',') });
                if (replacements != null && replacements.Any())
                {
                    foreach (var replacement in replacements)
                    {
                        replacement.brandCode = brandCode;
                        replacement.brandName = BrandDictionary.GetName(brandCode);
                        replacement.props = new List<Query_Part_DetailResult._prop>();
                        if (!string.IsNullOrEmpty(data.supersessionType))
                        {
                            replacement.props.Add(new Query_Part_DetailResult._prop { key = "替换类型", value = data.supersessionType });
                        }
                        result.replacements.Add(replacement);
                    }
                }
            }
            //4.配件附加属性处理
            var props = new List<Query_Part_DetailResult._prop>
            {
                new Query_Part_DetailResult._prop { key = "工程零件编号", value = result.engPartNo ?? string.Empty },
                new Query_Part_DetailResult._prop { key = "件数", value = result.quantity ?? string.Empty },
            };
            result.props = props.Where(q => !string.IsNullOrEmpty(q.value)).ToList();
            return result;
        }

        protected override dynamic GetModelsByPart(DbRESTFulRepository repository, int pageIndex, int pageSize, string brandCode, string partCode)
        {
            return repository.Invoke(CSIs.Query_Models_By_Part_For_Jaguar, new { pageIndex, pageSize, brandCode, partCode = partCode });
        }

        protected override dynamic GetHotPointsByPart(DbRESTFulRepository repository, string brandCode, string partCode, IEnumerable<string> imageIds)
        {
            return repository.Invoke(CSIs.Query_HotPoints_By_Part_For_Jaguar, new { brandCode, partCode = partCode, imageIds });
        }
        protected override List<SearchSubGroupResults> GetSearchResults(DbRESTFulRepository repository, string brandCode, string[] partCodes, string selectorId)
        {
            return repository.Invoke<SearchSubGroupResults>(CSIs.Search_SubGroups_By_PartCodes_For_Jaguar, new { brandCode, partCodes, selectorId });
        }

        protected override List<PartCatalog> GetPartCatalogs(DbRESTFulRepository repository, IEnumerable<string> partCodes, string selectorId, string brandCode, string vinCode)
        {
            List<PartCatalogResult> partCatalogResults = repository.Invoke<PartCatalogResult>(CSIs.Query_Part_Catalog_For_Jaguar, new { selectorId, partCodes });
            var mainGroups = partCatalogResults.Select(x => x.mainGroupId).Distinct().Select(q => new Query_MainGroupResult { id = q });
            string modelFeatures = repository.Invoke<string>(CSIs.Query_ModelFeature_By_SelectId_For_Jaguar, new { selectorId });
            mainGroups = FilterMaingroupsByModelFeatures2(repository, mainGroups, modelFeatures);
            var vinInfo = repository.Invoke(CSIs.Query_Vin_By_Code_For_Jaguar, new { vin = vinCode });
            string vinFeatures = vinInfo.featureIdListStr;
            mainGroups = FilterMaingroupsByVinFeatures(repository, mainGroups, vinFeatures);
            var mainGroupIds = mainGroups.Where(q => q.isBelongTo).Select(q => q.id);
            partCatalogResults = partCatalogResults.Where(q => mainGroupIds.Contains(q.mainGroupId)).ToList();

            var subGroups = partCatalogResults.Select(x => x.subGroupId).Distinct().Select(q => new Query_SubGroupResult { id = q.ToString() });
            subGroups = FilterSubgroupsByModelFeatures2(repository, subGroups, modelFeatures);
            subGroups = FilterSubGroupsByVin2(repository, subGroups.ToList(), vinCode, vinFeatures);
            var subGroupIds = subGroups.Where(q => q.belongTo).Select(q => q.id);
            partCatalogResults = partCatalogResults.Where(q => subGroupIds.Contains(q.subGroupId.ToString())).ToList();

            partCatalogResults = FilterPartsByModelFeatures2(repository, partCatalogResults, selectorId, modelFeatures);
            FilterPartsByVin2(repository, ref partCatalogResults, vinCode, selectorId, vinFeatures);
            partCatalogResults = partCatalogResults.Where(q => q.belongToVin).ToList();
            var hotPointsModel = repository.Invoke(CSIs.Query_HotPoints_By_Parts_For_Jaguar, new { brandCode, partIds = partCatalogResults.Select(q => q.id).Distinct() });
            JArray allPoints = JArray.FromObject(hotPointsModel);
            foreach (var item in partCatalogResults)
            {
                //2.1适用车型多张图片处理
                var imgs = allPoints.Where(p => p.Value<string>("partId") == item.id).Select(p => p.Value<string>("url")).Distinct().Select(x => new _imgs { url = x }).ToList();
                foreach (var img in imgs)
                {
                    //2.1.1适用车型每张图片对应的热点处理
                    img.points = allPoints.Where(p => p.Value<string>("url") == img.url && p.Value<string>("partId") == item.id)
                                       .Select(p => p.ToObject<_imgs._points>()).ToList();
                }
                item.imgs = imgs;
            }
            return BuildPartCatalogList(partCatalogResults);
        }

        public override object RealTimeQueryPartPrice(DbRESTFulRepository repository, JObject param)
        {
            var brandCode = param.Value<string>(ParamFields._brandCode);
            var partCode = param.Value<string>(ParamFields._partCode);
            EPCOnlineQueryService epcOnlineQueryService = new EPCOnlineQueryService();
            var queryRes = epcOnlineQueryService.RealTimeQueryPartPrice(partCode, brandCode);

            decimal price, cost;
            CheckOnlinePriceQueryRes(queryRes, partCode, out price, out cost);
            return new { partCode, brandCode, price, cost };
        }
        void CheckOnlinePriceQueryRes(JObject queryRes, string partCode, out decimal price, out decimal cost)
        {
            if (queryRes == null)
            {
                LoggerManager.Logger.LogError("JaguarQueryInterceptor.QueryPrice, queryRes is null");

                throw new Exception($"系统繁忙，请稍后再试！({partCode})");
            }
            bool hasError = queryRes["HasError"].ToObject<bool>();
            if (hasError)
            {
                string errMsg = queryRes["ErrorMessage"].ToObject<string>();
                LoggerManager.Logger.LogError($"JaguarQueryInterceptor.QueryPrice, hasError,{errMsg} ");

                throw new Exception($"系统繁忙，请稍后再试！({partCode})");
            }
            var data = queryRes["Data"];
            if (data == null)
            {
                LoggerManager.Logger.LogError("JaguarQueryInterceptor.QueryPrice, data is null");

                throw new Exception($"系统繁忙，请稍后再试！({partCode})");
            }

            price = 0;
            var priceObj = data["price"];
            if (priceObj != null && !string.IsNullOrEmpty(priceObj.Value<string>()))
            {
                price = priceObj.ToObject<decimal>();
            }

            cost = 0;
            var costObj = data["cost"];
            if (costObj != null && !string.IsNullOrEmpty(costObj.Value<string>()))
            {
                cost = costObj.ToObject<decimal>();
            }
        }

        #region modelfeature filter
        /// <summary>
        /// 1,2|1,3,4|2,5
        /// </summary>
        /// <param name="modelFeatures"></param>
        /// <param name="features"></param>
        List<Query_PartsResult> FilterPartsByModelFeatures(DbRESTFulRepository repository, List<Query_PartsResult> partList, string selectorId)
        {

            if (partList == null || !partList.Any())
            {
                return null;
            }

            string modelFeatures = repository.Invoke<string>(CSIs.Query_ModelFeature_By_SelectId_For_Jaguar, new { selectorId });
            if (string.IsNullOrEmpty(modelFeatures))
            {
                return partList;
            }
            List<Query_PartsResult> result = new List<Query_PartsResult>();

            List<string> allFeatureIds = new List<string>();
            List<string> featureIds_model = modelFeatures.Split(new char[] { ',' }).ToList();
            allFeatureIds.AddRange(featureIds_model);

            foreach (var part in partList)
            {
                if (!string.IsNullOrEmpty(part.featureCodes))
                {
                    List<string> orFeatureIdList = part.featureCodes.Split(new char[] { '|' }).ToList();
                    foreach (var item in orFeatureIdList)
                    {
                        List<string> andFeatureIdList = item.Split(new char[] { ',' }).ToList();
                        foreach (var f in andFeatureIdList)
                        {
                            if (!allFeatureIds.Contains(f))
                            {
                                allFeatureIds.Add(f);
                            }
                        }
                    }
                }
            }
            List<Feature_Jaguar> featuresList = GetFeaturesByIds(repository, allFeatureIds);
            List<Feature_Jaguar> modelFeatureList = featuresList.Where(e => featureIds_model.Contains(e.featureId.ToString())).ToList();
            foreach (var part in partList)
            {
                bool tmpRes = false;
                if (string.IsNullOrEmpty(part.featureCodes))
                {
                    tmpRes = true;
                }
                else
                {
                    List<string> orFeatureIdList = part.featureCodes.Split(new char[] { '|' }).ToList();
                    foreach (var item in orFeatureIdList)
                    {
                        List<string> andFeatureIdList = item.Split(new char[] { ',' }).ToList();
                        List<Feature_Jaguar> andFeatures = featuresList.Where(e => andFeatureIdList.Contains(e.featureId.ToString())).ToList();

                        bool andBoolRes = true;
                        foreach (var andItem in andFeatures)
                        {
                            var tmpFeature = modelFeatureList.FirstOrDefault(e => e.familyId == andItem.familyId);
                            if (tmpFeature != null && tmpFeature.featureId != andItem.featureId)
                            {
                                andBoolRes = false;
                                break;
                            }
                        }
                        if (andBoolRes)
                        {
                            tmpRes = true;
                            break;
                        }
                    }
                }
                if (tmpRes)
                {
                    result.Add(part);
                }
            }
            return result;
        }

        List<PartCatalogResult> FilterPartsByModelFeatures2(DbRESTFulRepository repository, List<PartCatalogResult> partList, string selectorId, string modelFeatures)
        {

            if (partList == null || !partList.Any())
            {
                return null;
            }
            if (string.IsNullOrEmpty(modelFeatures))
            {
                return partList;
            }
            List<PartCatalogResult> result = new List<PartCatalogResult>();

            List<string> allFeatureIds = new List<string>();
            List<string> featureIds_model = modelFeatures.Split(new char[] { ',' }).ToList();
            allFeatureIds.AddRange(featureIds_model);

            foreach (var part in partList)
            {
                if (!string.IsNullOrEmpty(part.featureCodes))
                {
                    List<string> orFeatureIdList = part.featureCodes.Split(new char[] { '|' }).ToList();
                    foreach (var item in orFeatureIdList)
                    {
                        List<string> andFeatureIdList = item.Split(new char[] { ',' }).ToList();
                        foreach (var f in andFeatureIdList)
                        {
                            if (!allFeatureIds.Contains(f))
                            {
                                allFeatureIds.Add(f);
                            }
                        }
                    }
                }
            }
            List<Feature_Jaguar> featuresList = GetFeaturesByIds(repository, allFeatureIds);
            List<Feature_Jaguar> modelFeatureList = featuresList.Where(e => featureIds_model.Contains(e.featureId.ToString())).ToList();
            foreach (var part in partList)
            {
                bool tmpRes = false;
                if (string.IsNullOrEmpty(part.featureCodes))
                {
                    tmpRes = true;
                }
                else
                {
                    List<string> orFeatureIdList = part.featureCodes.Split(new char[] { '|' }).ToList();
                    foreach (var item in orFeatureIdList)
                    {
                        List<string> andFeatureIdList = item.Split(new char[] { ',' }).ToList();
                        List<Feature_Jaguar> andFeatures = featuresList.Where(e => andFeatureIdList.Contains(e.featureId.ToString())).ToList();

                        bool andBoolRes = true;
                        foreach (var andItem in andFeatures)
                        {
                            var tmpFeature = modelFeatureList.FirstOrDefault(e => e.familyId == andItem.familyId);
                            if (tmpFeature != null && tmpFeature.featureId != andItem.featureId)
                            {
                                andBoolRes = false;
                                break;
                            }
                        }
                        if (andBoolRes)
                        {
                            tmpRes = true;
                            break;
                        }
                    }
                }
                if (tmpRes)
                {
                    result.Add(part);
                }
            }
            return result;
        }

        List<Feature_Jaguar> GetFeaturesByIds(DbRESTFulRepository repository, List<string> featureIds)
        {
            List<Feature_Jaguar> result = new List<Feature_Jaguar>();
            if (featureIds != null && featureIds.Any())
            {
                result = repository.Invoke<Feature_Jaguar>(CSIs.Get_Features_For_Jaguar, new { featureIds });
            }
            return result;
        }

        IEnumerable<Query_SubGroupResult> FilterSubgroupsByModelFeatures(DbRESTFulRepository repository, IEnumerable<Query_SubGroupResult> subgroupList, string selectorId)
        {
            if (subgroupList == null || !subgroupList.Any())
            {
                return null;
            }
            List<Query_SubGroupResult> result = new List<Query_SubGroupResult>();
            var subgroupids = subgroupList.Select(e => e.id);

            string modelFeatures = repository.Invoke<string>(CSIs.Query_ModelFeature_By_SelectId_For_Jaguar, new { selectorId });
            if (string.IsNullOrEmpty(modelFeatures))
            {
                result = subgroupList.ToList();
                return result;
            }
            List<string> featureIds_model = modelFeatures.Split(new char[] { ',' }).ToList();
            List<string> allFeatureIds = new List<string>();
            allFeatureIds.AddRange(featureIds_model);

            List<JlrSubGroupFilter> _subgroupFilters = repository.Invoke<JlrSubGroupFilter>(CSIs.Query_Subgroup_Filter_For_Jaguar, new { subgroupids });
            if (_subgroupFilters == null || !_subgroupFilters.Any())
            {
                result = subgroupList.ToList();
                return result;
            }

            var subgroupFilterIds = _subgroupFilters.Select(e => e.filterIds);
            foreach (var item in subgroupFilterIds)
            {
                allFeatureIds.AddRange(item.Split(new char[] { ',' }));
            }
            allFeatureIds = allFeatureIds.Distinct().ToList();
            List<Feature_Jaguar> featuresList = GetFeaturesByIds(repository, allFeatureIds);
            List<Feature_Jaguar> modelFeatureList = featuresList.Where(e => featureIds_model.Contains(e.featureId.ToString())).ToList();
            foreach (var sub in subgroupList)
            {
                bool tmpRes = false;
                var subFilters = _subgroupFilters.Where(e => e.subgroupId.ToString() == sub.id);
                if (subFilters == null || !subFilters.Any())
                {
                    tmpRes = true;
                }
                else
                {
                    foreach (var item in subFilters)
                    {
                        List<string> andFeatureIdList = item.filterIds.Split(new char[] { ',' }).ToList();
                        List<Feature_Jaguar> andFeatures = featuresList.Where(e => andFeatureIdList.Contains(e.featureId.ToString())).ToList();

                        bool andBoolRes = true;
                        foreach (var andItem in andFeatures)
                        {
                            var tmpFeatures = modelFeatureList.Where(e => e.familyId == andItem.familyId);
                            if (tmpFeatures != null && tmpFeatures.Any())
                            {
                                bool t1 = false;
                                foreach (var tmpFeatureItem in tmpFeatures)
                                {
                                    if (tmpFeatureItem.featureId == andItem.featureId || (tmpFeatureItem.similarFeatureIds ?? "").Contains(andItem.featureId.ToString()))
                                    {
                                        t1 = true;
                                        break;
                                    }
                                }
                                if (!t1)
                                {
                                    andBoolRes = false;
                                    break;
                                }
                            }
                        }
                        if (andBoolRes)
                        {
                            tmpRes = true;
                            break;
                        }
                    }
                }
                if (tmpRes)
                {
                    result.Add(sub);
                }
            }
            return result;
        }

        IEnumerable<Query_SubGroupResult> FilterSubgroupsByModelFeatures2(DbRESTFulRepository repository, IEnumerable<Query_SubGroupResult> subgroupList, string modelFeatures)
        {
            if (subgroupList == null || !subgroupList.Any())
            {
                return null;
            }
            List<Query_SubGroupResult> result = new List<Query_SubGroupResult>();
            var subgroupids = subgroupList.Select(e => e.id);

            if (string.IsNullOrEmpty(modelFeatures))
            {
                result = subgroupList.ToList();
                return result;
            }
            List<string> featureIds_model = modelFeatures.Split(new char[] { ',' }).ToList();
            List<string> allFeatureIds = new List<string>();
            allFeatureIds.AddRange(featureIds_model);

            List<JlrSubGroupFilter> _subgroupFilters = repository.Invoke<JlrSubGroupFilter>(CSIs.Query_Subgroup_Filter_For_Jaguar, new { subgroupids });
            if (_subgroupFilters == null || !_subgroupFilters.Any())
            {
                result = subgroupList.ToList();
                return result;
            }

            var subgroupFilterIds = _subgroupFilters.Select(e => e.filterIds);
            foreach (var item in subgroupFilterIds)
            {
                allFeatureIds.AddRange(item.Split(new char[] { ',' }));
            }
            allFeatureIds = allFeatureIds.Distinct().ToList();
            List<Feature_Jaguar> featuresList = GetFeaturesByIds(repository, allFeatureIds);
            List<Feature_Jaguar> modelFeatureList = featuresList.Where(e => featureIds_model.Contains(e.featureId.ToString())).ToList();
            foreach (var sub in subgroupList)
            {
                bool tmpRes = false;
                var subFilters = _subgroupFilters.Where(e => e.subgroupId.ToString() == sub.id);
                if (subFilters == null || !subFilters.Any())
                {
                    tmpRes = true;
                }
                else
                {
                    foreach (var item in subFilters)
                    {
                        List<string> andFeatureIdList = item.filterIds.Split(new char[] { ',' }).ToList();
                        List<Feature_Jaguar> andFeatures = featuresList.Where(e => andFeatureIdList.Contains(e.featureId.ToString())).ToList();

                        bool andBoolRes = true;
                        foreach (var andItem in andFeatures)
                        {
                            var tmpFeatures = modelFeatureList.Where(e => e.familyId == andItem.familyId);
                            if (tmpFeatures != null && tmpFeatures.Any())
                            {
                                bool t1 = false;
                                foreach (var tmpFeatureItem in tmpFeatures)
                                {
                                    if (tmpFeatureItem.featureId == andItem.featureId || (tmpFeatureItem.similarFeatureIds ?? "").Contains(andItem.featureId.ToString()))
                                    {
                                        t1 = true;
                                        break;
                                    }
                                }
                                if (!t1)
                                {
                                    andBoolRes = false;
                                    break;
                                }
                            }
                        }
                        if (andBoolRes)
                        {
                            tmpRes = true;
                            break;
                        }
                    }
                }
                if (tmpRes)
                {
                    result.Add(sub);
                }
            }
            return result;
        }

        IEnumerable<Query_MainGroupResult> FilterMaingroupsByModelFeatures(DbRESTFulRepository repository, IEnumerable<Query_MainGroupResult> maingroupList, string selectorId)
        {
            if (maingroupList == null || !maingroupList.Any())
            {
                return null;
            }
            List<Query_MainGroupResult> result = new List<Query_MainGroupResult>();
            var maingroupIds = maingroupList.Select(e => e.id);

            string modelFeatures = repository.Invoke<string>(CSIs.Query_ModelFeature_By_SelectId_For_Jaguar, new { selectorId });
            if (string.IsNullOrEmpty(modelFeatures))
            {
                result = maingroupList.ToList();
                return result;
            }
            List<string> featureIds_model = modelFeatures.Split(new char[] { ',' }).ToList();
            List<string> allFeatureIds = new List<string>();
            allFeatureIds.AddRange(featureIds_model);

            List<JlrMainGroupFilter> maingroupFilters = repository.Invoke<JlrMainGroupFilter>(CSIs.Query_Maingroup_Filter_For_Jaguar, new { maingroupIds });
            if (maingroupFilters == null || !maingroupFilters.Any())
            {
                result = maingroupList.ToList();
                return result;
            }

            var maingroupFilterIds = maingroupFilters.Select(e => e.filterIds);
            foreach (var item in maingroupFilterIds)
            {
                allFeatureIds.AddRange(item.Split(new char[] { ',' }));
            }
            allFeatureIds = allFeatureIds.Distinct().ToList();
            List<Feature_Jaguar> featuresList = GetFeaturesByIds(repository, allFeatureIds);
            List<Feature_Jaguar> modelFeatureList = featuresList.Where(e => featureIds_model.Contains(e.featureId.ToString())).ToList();
            foreach (var main in maingroupList)
            {
                bool tmpRes = false;
                var mainFilters = maingroupFilters.Where(e => e.maingroupId.ToString() == main.id);
                if (mainFilters == null || !mainFilters.Any())
                {
                    tmpRes = true;
                }
                else
                {
                    foreach (var item in mainFilters)
                    {
                        List<string> andFeatureIdList = item.filterIds.Split(new char[] { ',' }).ToList();
                        List<Feature_Jaguar> andFeatures = featuresList.Where(e => andFeatureIdList.Contains(e.featureId.ToString())).ToList();

                        bool andBoolRes = true;
                        foreach (var andItem in andFeatures)
                        {
                            var tmpFeatures = modelFeatureList.Where(e => e.familyId == andItem.familyId);
                            if (tmpFeatures != null && tmpFeatures.Any())
                            {
                                bool t1 = false;
                                foreach (var tmpFeatureItem in tmpFeatures)
                                {
                                    if (tmpFeatureItem.featureId == andItem.featureId || (tmpFeatureItem.similarFeatureIds ?? "").Contains(andItem.featureId.ToString()))
                                    {
                                        t1 = true;
                                        break;
                                    }
                                }
                                if (!t1)
                                {
                                    andBoolRes = false;
                                    break;
                                }
                            }
                        }
                        if (andBoolRes)
                        {
                            tmpRes = true;
                            break;
                        }
                    }
                }
                if (tmpRes)
                {
                    result.Add(main);
                }
            }
            return result;
        }

        IEnumerable<Query_MainGroupResult> FilterMaingroupsByModelFeatures2(DbRESTFulRepository repository, IEnumerable<Query_MainGroupResult> maingroupList, string modelFeatures)
        {
            if (maingroupList == null || !maingroupList.Any())
            {
                return null;
            }
            List<Query_MainGroupResult> result = new List<Query_MainGroupResult>();
            var maingroupIds = maingroupList.Select(e => e.id);

            if (string.IsNullOrEmpty(modelFeatures))
            {
                result = maingroupList.ToList();
                return result;
            }
            List<string> featureIds_model = modelFeatures.Split(new char[] { ',' }).ToList();
            List<string> allFeatureIds = new List<string>();
            allFeatureIds.AddRange(featureIds_model);

            List<JlrMainGroupFilter> maingroupFilters = repository.Invoke<JlrMainGroupFilter>(CSIs.Query_Maingroup_Filter_For_Jaguar, new { maingroupIds });
            if (maingroupFilters == null || !maingroupFilters.Any())
            {
                result = maingroupList.ToList();
                return result;
            }

            var maingroupFilterIds = maingroupFilters.Select(e => e.filterIds);
            foreach (var item in maingroupFilterIds)
            {
                allFeatureIds.AddRange(item.Split(new char[] { ',' }));
            }
            allFeatureIds = allFeatureIds.Distinct().ToList();
            List<Feature_Jaguar> featuresList = GetFeaturesByIds(repository, allFeatureIds);
            List<Feature_Jaguar> modelFeatureList = featuresList.Where(e => featureIds_model.Contains(e.featureId.ToString())).ToList();
            foreach (var main in maingroupList)
            {
                bool tmpRes = false;
                var mainFilters = maingroupFilters.Where(e => e.maingroupId.ToString() == main.id);
                if (mainFilters == null || !mainFilters.Any())
                {
                    tmpRes = true;
                }
                else
                {
                    foreach (var item in mainFilters)
                    {
                        List<string> andFeatureIdList = item.filterIds.Split(new char[] { ',' }).ToList();
                        List<Feature_Jaguar> andFeatures = featuresList.Where(e => andFeatureIdList.Contains(e.featureId.ToString())).ToList();

                        bool andBoolRes = true;
                        foreach (var andItem in andFeatures)
                        {
                            var tmpFeatures = modelFeatureList.Where(e => e.familyId == andItem.familyId);
                            if (tmpFeatures != null && tmpFeatures.Any())
                            {
                                bool t1 = false;
                                foreach (var tmpFeatureItem in tmpFeatures)
                                {
                                    if (tmpFeatureItem.featureId == andItem.featureId || (tmpFeatureItem.similarFeatureIds ?? "").Contains(andItem.featureId.ToString()))
                                    {
                                        t1 = true;
                                        break;
                                    }
                                }
                                if (!t1)
                                {
                                    andBoolRes = false;
                                    break;
                                }
                            }
                        }
                        if (andBoolRes)
                        {
                            tmpRes = true;
                            break;
                        }
                    }
                }
                if (tmpRes)
                {
                    result.Add(main);
                }
            }
            return result;
        }


        IEnumerable<Query_MainGroupResult> FilterMaingroupsByVinFeatures(DbRESTFulRepository repository, IEnumerable<Query_MainGroupResult> maingroupList, string vinFeatures)
        {

            if (maingroupList == null || maingroupList.Count() <= 0)
            {
                return null;
            }
            if (string.IsNullOrEmpty(vinFeatures))
            {
                return maingroupList;
            }
            List<Query_MainGroupResult> result = new List<Query_MainGroupResult>();

            List<string> allFeatureIds = new List<string>();
            List<string> featureIds_vin = vinFeatures.Split(new char[] { ',' }).ToList();
            allFeatureIds.AddRange(featureIds_vin);

            var maingroupIds = maingroupList.Select(e => e.id);
            List<JlrMainGroupFilter> maingroupFilters = repository.Invoke<JlrMainGroupFilter>(CSIs.Query_Maingroup_Filter_For_Jaguar, new { maingroupIds });
            if (maingroupFilters == null || !maingroupFilters.Any())
            {
                return maingroupList;
            }
            var filterIds = maingroupFilters.Where(e => !string.IsNullOrEmpty(e.filterIds)).Select(e => e.filterIds);
            if (filterIds == null || !filterIds.Any())
            {
                return maingroupList;
            }
            foreach (var item in filterIds)
            {
                allFeatureIds.AddRange(item.Split(new char[] { ',' }));
            }
            allFeatureIds = allFeatureIds.Distinct().ToList();

            List<Feature_Jaguar> featuresList = GetFeaturesByIds(repository, allFeatureIds);
            List<Feature_Jaguar> vinFeatureList = featuresList.Where(e => featureIds_vin.Contains(e.featureId.ToString())).ToList();
            foreach (var group in maingroupList)
            {
                bool tmpRes = false;
                var mainFilters = maingroupFilters.Where(e => e.maingroupId.ToString() == group.id);
                if (mainFilters == null || !mainFilters.Any())
                {
                    tmpRes = true;
                }
                else
                {
                    foreach (var item in mainFilters)
                    {
                        List<string> andFeatureIdList = item.filterIds.Split(new char[] { ',' }).ToList();
                        List<Feature_Jaguar> andFeatures = featuresList.Where(e => andFeatureIdList.Contains(e.featureId.ToString())).ToList();

                        bool andBoolRes = true;
                        foreach (var andItem in andFeatures)
                        {
                            var tmpFeature = vinFeatureList.FirstOrDefault(e => e.familyId == andItem.familyId);
                            if (tmpFeature != null && tmpFeature.featureId != andItem.featureId && !(tmpFeature.similarFeatureIds ?? "").Contains(andItem.featureId.ToString()))
                            {
                                if (!CheckSameFamilyFeature(tmpFeature, andItem))
                                {
                                    andBoolRes = false;
                                    break;
                                }
                            }
                        }
                        if (andBoolRes)
                        {
                            tmpRes = true;
                            break;
                        }
                    }
                }
                if (tmpRes)
                {
                    result.Add(group);
                }
            }
            return result;
        }

        #endregion

        protected override List<QuickPartResult> QuickQueryPartsFilterByUsage_Vin(DbRESTFulRepository repository, List<QuickPartResult> parts, int selectorId, string vin)
        {
            List<QuickPartResult> ret = new List<QuickPartResult>();
            if (!string.IsNullOrEmpty(vin) && parts != null && parts.Any())
            {
                List<string> partCodes = parts.Select(e => e.partCode).Distinct().ToList();
                List<Query_PartsResult> partUsages = repository.Invoke<Query_PartsResult>(CSIs.Query_Quick_PartUsage_For_Jaguar, new { selectorId, partCodes });
                if (partUsages != null && partUsages.Any())
                {
                    List<string> usedPartCodes = new List<string>();
                    var vinInfo = repository.Invoke(CSIs.Get_VinFilters_For_Jaguar, new { vin });
                    if (vinInfo != null)
                    {
                        List<Feature_Jaguar> featuresList, vinFeatureList;
                        HandleFeatureIds(repository, partUsages, vinInfo.featureIdListStr, out featuresList, out vinFeatureList);
                        foreach (var info in partUsages)
                        {
                            if (!string.IsNullOrEmpty(info.rangeStart) && CompareVinRange(vin, info.rangeStart) < 0)
                            {
                                continue;
                            }

                            if (!string.IsNullOrEmpty(info.rangeEnd) && CompareVinRange(vin, info.rangeEnd) > 0)
                            {
                                continue;
                            }
                            bool tmpRes = false;
                            if (string.IsNullOrEmpty(info.featureCodes))
                            {
                                tmpRes = true;
                            }
                            else
                            {
                                List<string> orFeatureIdList = info.featureCodes.Split(new char[] { '|' }).ToList();
                                foreach (var item in orFeatureIdList)
                                {
                                    List<string> andFeatureIdList = item.Split(new char[] { ',' }).ToList();
                                    List<Feature_Jaguar> andFeatures = featuresList.Where(e => andFeatureIdList.Contains(e.featureId.ToString())).ToList();

                                    bool andBoolRes = true;
                                    foreach (var andItem in andFeatures)
                                    {
                                        var tmpFeature = vinFeatureList.FirstOrDefault(e => e.familyId == andItem.familyId);
                                        if (tmpFeature != null && tmpFeature.featureId != andItem.featureId && !(tmpFeature.similarFeatureIds ?? "").Contains(andItem.featureId.ToString()))
                                        {
                                            if (!CheckSameFamilyFeature(tmpFeature, andItem))
                                            {
                                                andBoolRes = false;
                                                break;
                                            }
                                        }
                                    }
                                    if (andBoolRes)
                                    {
                                        tmpRes = true;
                                        break;
                                    }
                                }
                            }
                            if (tmpRes)
                            {
                                usedPartCodes.Add(info.partCode);
                            }
                        }

                        if (usedPartCodes.Any())
                        {
                            ret = parts.Where(e => usedPartCodes.Contains(e.partCode)).ToList();
                        }
                    }
                }
            }
            return ret;
        }
    }
}



